package com.xkcoding.sharding.jdbc.hardingrules;

import cn.hutool.core.date.DateTime;
import com.google.common.collect.Range;
import lombok.extern.slf4j.Slf4j;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 凭证表分表逻辑
 *
 * @author liguoxiong
 * @date 2021/1/18
 */
@Slf4j
@Component
public class MonthTableShardingAlgorithm implements PreciseShardingAlgorithm<Date>, RangeShardingAlgorithm<Date> {
    public static final String yyyyMM = "yyyyMM";

    /**
     * 分片字段，请求时间
     */
    private static final String REQUEST_DATE = "request_date";



    /**
     * 按月分表
     *
     * @param availableTargetNames
     * @param shardingValue
     * @return
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
        log.debug("MonthTableShardingAlgorithm availableTargetNames:{},shardingValue{}", availableTargetNames,
            shardingValue);
        String tableName =format(shardingValue.getValue(),yyyyMM);
        String target = availableTargetNames.stream().findFirst().orElse(null) +
            "_"+ tableName;
        log.info("the MonthTableShardingAlgorithm target table name: {}", target);
        return target;
    }

    /**
     * 范围分表查询
     *
     * @param availableTargetNames
     * @param shardingValue
     * @return
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {
        log.debug("Range collection:{},rangeShardingValue{}", availableTargetNames, shardingValue);
        Collection<String> targetNames = new ArrayList<>();
        Range<Date> valueRange = shardingValue.getValueRange();
        Date startTime = valueRange.lowerEndpoint();
        Date endTime = valueRange.upperEndpoint();
        Calendar calendar = Calendar.getInstance();
        //时间跨月处理
        while (startTime.getTime() <= endTime.getTime()) {
            targetNames.add(availableTargetNames.stream().findFirst().orElse(null) +
               "_" +
                format(startTime,yyyyMM));
            calendar.setTime(startTime);
            calendar.add(Calendar.MONTH, 1);
            startTime = calendar.getTime();
        }
        log.info("the MonthTableShardingAlgorithm target table name: {}", targetNames);
        return targetNames;
    }
    public static String format(Date date, String pattern) {
        return date == null ? null : (new DateTime(date)).toString(pattern);
    }
}
